package com.aiwiown.snackmq.cluster.serialization;

import com.aiwiown.snackmq.cluster.routing.Exchange;
import com.aiwiown.snackmq.cluster.routing.exchange.DirectExchange;
import com.aiwiown.snackmq.cluster.routing.exchange.FanoutExchange;
import com.aiwiown.snackmq.cluster.routing.exchange.TopicExchange;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;

import java.io.IOException;

/**
 * 【最终修复】为 Exchange 接口提供一个健壮的 Gson TypeAdapter。
 * 这个适配器解决了 Gson 无法反序列化接口的问题，并能正确处理多态性。
 *
 * 它在序列化时，将对象的具体数据和类型标识（如 "DIRECT"）写入 JSON。
 * 在反序列化时，根据这个类型标识来创建正确的对象实例。
 *
 * 这个实现修复了之前版本因错误使用 Class.forName() 导致的 ClassNotFoundException。
 */
public class ExchangeTypeAdapter extends TypeAdapter<Exchange> {

    private static final String TYPE_FIELD = "type";
    private static final String DATA_FIELD = "data";

    @Override
    public void write(JsonWriter out, Exchange value) throws IOException {
        if (value == null) {
            out.nullValue();
            return;
        }
        // 使用一个不包含此适配器的新Gson实例来序列化，以避免无限递归
        Gson gson = new Gson();
        out.beginObject();
        // 1. 写入类型标识
        out.name(TYPE_FIELD);
        // 假设 Exchange 接口有 getType() 方法返回一个包含 name() 的枚举
        out.value(value.getType().name());
        // 2. 写入具体数据
        out.name(DATA_FIELD);
        gson.toJson(gson.toJsonTree(value), out);
        out.endObject();
    }

    @Override
    public Exchange read(JsonReader in) throws IOException {
        Gson gson = new Gson();
        JsonObject jsonObject = gson.fromJson(in, JsonObject.class);

        JsonPrimitive typePrimitive = jsonObject.getAsJsonPrimitive(TYPE_FIELD);
        if (typePrimitive == null) {
            throw new JsonParseException("Missing '" + TYPE_FIELD + "' property in Exchange JSON object");
        }
        String typeName = typePrimitive.getAsString();

        JsonElement dataElement = jsonObject.get(DATA_FIELD);
        if (dataElement == null) {
            throw new JsonParseException("Missing '" + DATA_FIELD + "' property in Exchange JSON object");
        }

        // 【核心修复】: 将从 JSON 中读取的简单类型字符串（如 "DIRECT"）映射到其完全限定的 Java 类。
        // 不能直接使用 Class.forName(typeName)。
        switch (typeName.toUpperCase()) {
            case "DIRECT":
                return gson.fromJson(dataElement, DirectExchange.class);
            case "FANOUT":
                return gson.fromJson(dataElement, FanoutExchange.class);
            case "TOPIC":
                return gson.fromJson(dataElement, TopicExchange.class);
            // 如果还有其他 Exchange 类型，在这里添加 case
            default:
                // 抛出更明确的异常
                throw new JsonParseException("Unknown or unsupported Exchange type found in snapshot: " + typeName);
        }
    }
}